package problems;

public class Euler028 extends AbstractEuler {

	private static final int SPIRAL_SIZE = 1001;
	
	public enum Direction {
		RIGHT	(1 ,  0),
		DOWN	(0 , -1),
		LEFT	(-1,  0),
		UP		(0 ,  1);
		
		Direction(int x, int y) {
			this.dx = x;
			this.dy = y;
		}
		
		int dx, dy;
		
		Direction getNextDir() {
			switch(this) {
				case RIGHT:	return DOWN;
				case DOWN:	return LEFT;
				case LEFT:	return UP;
				case UP:	return RIGHT;
				
				default:	throw new RuntimeException("unknown direction: " + this);
			}
		}
		
	}
	
	@Override
	public Number calculate() {
		
		//initialize spiral
		int[][] spiral = new int[SPIRAL_SIZE][SPIRAL_SIZE];
		
		int
		x = (SPIRAL_SIZE / 2) - 1,
		y = SPIRAL_SIZE / 2,
		counter = 1;
		
		Direction dir = Direction.RIGHT;
		
		while (counter <= SPIRAL_SIZE * SPIRAL_SIZE) {
			x+=dir.dx;
			y+=dir.dy;
			spiral[x][y] = counter;
			counter++;
			
			if (spiral[x + dir.getNextDir().dx][y + dir.getNextDir().dy] == 0) {
				dir = dir.getNextDir();
			}
		}
		
		//add values along both diagonals
		long total = -1; //account for the double-counted center cell
		
		for (int i = 0; i < SPIRAL_SIZE; i++) {
			total+=spiral[i][i];
			total+=spiral[i][SPIRAL_SIZE - i - 1];
		}
		
		return total;
		
	}
	
	@Override
	protected Number getCorrectAnswer() {
		return 669171001L;
	}

}
